#ifndef QSLOG_H
#define QSLOG_H

#include "QsLogLevel.h"
#include "QsLogDest.h"
#include <QDebug>
#include <QString>

#define QS_LOG_VERSION "2.0b3"

namespace QsLogging
{
class Destination;
class LoggerImpl; // d 指针

class QSLOG_SHARED_OBJECT Logger
{
public:
    // 获取日志记录器单例实例
    static Logger& instance();
    // 销毁日志记录器实例
    static void destroyInstance();
    // 从日志消息字符串中提取日志级别
    static Level levelFromLogMessage(const QString& logMessage, bool* conversionSucceeded = 0);

    // 析构函数
    ~Logger();

    //! 添加日志消息目标。不要添加空目标。
    void addDestination(DestinationPtr destination);
    //! 级别 < 'newLevel' 的日志将被忽略
    void setLoggingLevel(Level newLevel);
    //! 默认级别是 INFO
    Level loggingLevel() const;
    //! 设置为 false 以禁用日志消息中的时间戳包含
    void setIncludeTimestamp(bool e);
    //! 默认值为 true。
    bool includeTimestamp() const;
    //! 设置为 false 以禁用日志消息中的日志级别包含
    void setIncludeLogLevel(bool l);
    //! 默认值为 true。
    bool includeLogLevel() const;

    //! 辅助类将流式传输转发给 QDebug 并构建最终的日志消息。
    class QSLOG_SHARED_OBJECT Helper
    {
    public:
        // 构造函数，指定日志级别
        explicit Helper(Level logLevel) :
            level(logLevel),
            qtDebug(&buffer)
        {}
        // 析构函数，写入日志
        ~Helper();
        // 获取调试流对象
        QDebug& stream(){ return qtDebug; }

    private:
        // 将消息写入日志
        void writeToLog();

        Level level;
        QString buffer;
        QDebug qtDebug;
	};

private:
    // 私有构造函数
    Logger();
    Logger(const Logger&);            // 不可用
    Logger& operator=(const Logger&); // 不可用

    // 将消息加入队列等待写入
    void enqueueWrite(const QString& message, Level level);
    // 将消息写入所有目标
    void write(const QString& message, Level level);

    LoggerImpl* d;

    friend class LogWriterRunnable;
};

} // 命名空间结束

//! 日志宏：定义 QS_LOG_LINE_NUMBERS 以在日志输出中获取文件和行号。
#ifndef QS_LOG_LINE_NUMBERS
#define QLOG_TRACE() \
    if (QsLogging::Logger::instance().loggingLevel() > QsLogging::TraceLevel) {} \
    else QsLogging::Logger::Helper(QsLogging::TraceLevel).stream()
#define QLOG_DEBUG() \
    if (QsLogging::Logger::instance().loggingLevel() > QsLogging::DebugLevel) {} \
    else QsLogging::Logger::Helper(QsLogging::DebugLevel).stream()
#define QLOG_INFO()  \
    if (QsLogging::Logger::instance().loggingLevel() > QsLogging::InfoLevel) {} \
    else QsLogging::Logger::Helper(QsLogging::InfoLevel).stream()
#define QLOG_WARN()  \
    if (QsLogging::Logger::instance().loggingLevel() > QsLogging::WarnLevel) {} \
    else QsLogging::Logger::Helper(QsLogging::WarnLevel).stream()
#define QLOG_ERROR() \
    if (QsLogging::Logger::instance().loggingLevel() > QsLogging::ErrorLevel) {} \
    else QsLogging::Logger::Helper(QsLogging::ErrorLevel).stream()
#define QLOG_FATAL() \
    if (QsLogging::Logger::instance().loggingLevel() > QsLogging::FatalLevel) {} \
    else QsLogging::Logger::Helper(QsLogging::FatalLevel).stream()
#else
#define QLOG_TRACE() \
    if (QsLogging::Logger::instance().loggingLevel() > QsLogging::TraceLevel) {} \
    else  QsLogging::Logger::Helper(QsLogging::TraceLevel).stream() << __FILE__ << '@' << __LINE__
#define QLOG_DEBUG() \
    if (QsLogging::Logger::instance().loggingLevel() > QsLogging::DebugLevel) {} \
    else QsLogging::Logger::Helper(QsLogging::DebugLevel).stream() << __FILE__ << '@' << __LINE__
#define QLOG_INFO()  \
    if (QsLogging::Logger::instance().loggingLevel() > QsLogging::InfoLevel) {} \
    else QsLogging::Logger::Helper(QsLogging::InfoLevel).stream() << __FILE__ << '@' << __LINE__
#define QLOG_WARN()  \
    if (QsLogging::Logger::instance().loggingLevel() > QsLogging::WarnLevel) {} \
    else QsLogging::Logger::Helper(QsLogging::WarnLevel).stream() << __FILE__ << '@' << __LINE__
#define QLOG_ERROR() \
    if (QsLogging::Logger::instance().loggingLevel() > QsLogging::ErrorLevel) {} \
    else QsLogging::Logger::Helper(QsLogging::ErrorLevel).stream() << __FILE__ << '@' << __LINE__
#define QLOG_FATAL() \
    if (QsLogging::Logger::instance().loggingLevel() > QsLogging::FatalLevel) {} \
    else QsLogging::Logger::Helper(QsLogging::FatalLevel).stream() << __FILE__ << '@' << __LINE__
#endif

#ifdef QS_LOG_DISABLE
#include "QsLogDisableForThisFile.h"
#endif

#endif // QSLOG_H
